package com.design.framework.utils.http;

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;

import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;

import org.apache.http.Header;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpEntityEnclosingRequestBase;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.methods.HttpRequestBase;
import org.apache.http.conn.ssl.NoopHostnameVerifier;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.design.framework.utils.http.bean.HttpClickRequest;
import com.design.framework.utils.http.bean.HttpClickResponse;

/**
 * HTTP工具类
 * @author  JohnDeng
 * @dateTime 2020年6月20日下午11:36:25	
 *
 */
public class HttpClickUtils {

  private static final int OK_VALUE = 200;

  private Logger log = LoggerFactory.getLogger(getClass());

  private CloseableHttpClient httpClick;

  private static final String UTF8 = "UTF-8";

  private void initHttpClick() {
    httpClick = HttpClientBuilder.create().build();
  }

  /**
   * HTTPs
   *
   * @author JohnDeng
   * @datetime 2019年8月13日下午2:23:43
   */
  private void createSslClientDefault() {
    try {
      X509TrustManager x509mgr = new X509TrustManager() {
        @Override
        public void checkClientTrusted(X509Certificate[] xcs, String string) {
        }

        @Override
        public void checkServerTrusted(X509Certificate[] xcs, String string) {
        }

        @Override
        public X509Certificate[] getAcceptedIssuers() {
          return null;
        }
      };
      SSLContext sslContext = SSLContext.getInstance("TLSv1.2");
      sslContext.init(null, new TrustManager[]{x509mgr}, new java.security.SecureRandom());
      SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(sslContext, NoopHostnameVerifier.INSTANCE);
      httpClick = HttpClients.custom().setSSLSocketFactory(sslsf).build();
    } catch (NoSuchAlgorithmException e) {
      e.printStackTrace();
    } catch (KeyManagementException e) {
      e.printStackTrace();
    }
  }


  /**
   * 默认form表单请求头
   *
   * @return
   * @author JohnDeng
   * @dateTime 2019年5月15日下午4:07:30
   */
  public static Map<String, String> defaultFromHeader() {
    Map<String, String> headerMap = new HashMap<>(4);
    headerMap.put("Content-type", "application/x-www-form-urlencoded;charset=utf-8");
    headerMap.put("Cache-Control", "max-age=0");
    headerMap.put("User-Agent", "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.0) ");
    headerMap.put("Accept", "application/json, text/html,text/javascript, */*");
    return headerMap;
  }


  /**
   * 默认JSON请求头
   *
   * @return
   * @author JohnDeng
   * @dateTime 2019年5月15日下午4:07:30
   */
  public static Map<String, String> defaultJsonHeader() {
    Map<String, String> headerMap = new HashMap<>(4);
    headerMap.put("Content-type", "application/json;charset=utf-8");
    headerMap.put("Cache-Control", "max-age=0");
    headerMap.put("User-Agent", "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.0) ");
    headerMap.put("Accept", "application/json, text/html,text/javascript, */*");
    return headerMap;
  }


  /**
   * 设置请求头
   *
   * @param request
   * @param httpRequestBase
   * @return
   * @author JohnDeng
   * @dateTime 2019年5月15日下午4:07:30
   */
  private HttpRequestBase setHttpRequestHeader(HttpClickRequest request, HttpRequestBase httpRequestBase) {
    Set<Map.Entry<String, String>> entrySet = request.getHeaders().entrySet();
    for (Map.Entry<String, String> e : entrySet) {
      httpRequestBase.setHeader(e.getKey(), e.getValue());
    }
    return httpRequestBase;
  }

  /**
   * 发送请求
   *
   * @param request
   * @param httpRequestBase
   * @author JohnDeng
   * @dateTime 2019年5月15日下午4:07:39
   * @return`
   */
  private HttpClickResponse sendRequest(HttpClickRequest request, HttpRequestBase httpRequestBase) {
    HttpClickResponse httpClickResponse = null;
    httpRequestBase = setHttpRequestHeader(request, httpRequestBase);
    try {
      if (httpRequestBase instanceof HttpEntityEnclosingRequestBase) {
        if (request.isStringEntityFlag()) {
          ((HttpEntityEnclosingRequestBase) httpRequestBase)
              .setEntity(new StringEntity(request.getJsonString(), UTF8));
        } else {
          ((HttpEntityEnclosingRequestBase) httpRequestBase)
              .setEntity(new UrlEncodedFormEntity(mapToNameValuePairList(request.getParams()), UTF8));
        }
      }
    } catch (UnsupportedEncodingException e) {
      e.printStackTrace();
    }
    try {
      CloseableHttpResponse response = httpClick.execute(httpRequestBase);
      Header[] headers = response.getAllHeaders();
      HttpEntity entity = response.getEntity();
      String responseString = EntityUtils.toString(entity, UTF8);
      Map<String, String> map = new HashMap<>(headers.length);
      for (Header header : headers) {
        map.put(header.getName(), header.getValue());
      }
      log.info("-----{}------",response.getStatusLine().getStatusCode() );
      log.info("-----{}------",response.getStatusLine());

      if (response.getStatusLine().getStatusCode() == OK_VALUE) {
        httpClickResponse = new HttpClickResponse();
        httpClickResponse.setStatusCode(response.getStatusLine().getStatusCode());
        httpClickResponse.setResponseHeadersMap(map);
        httpClickResponse.setBodyParams(responseString);
      }
    } catch (ClientProtocolException e) {
      e.printStackTrace();
    } catch (IOException e) {
      e.printStackTrace();
    } finally {
      this.close();
    }
    return httpClickResponse;
  }

  /**
   * 设置参数
   *
   * @param params
   * @return
   * @author JohnDeng
   * @dateTime 2019年5月15日下午4:59:45
   */
  private static List<NameValuePair> mapToNameValuePairList(Map<String, String> params) {
    List<NameValuePair> nvps = new ArrayList<NameValuePair>();
    if (params != null && params.size() > 0) {
      for (Entry<String, String> param : params.entrySet()) {
        nvps.add(new BasicNameValuePair(param.getKey(), param.getValue()));
      }
    }
    return nvps;
  }

  /**
   * 设置超时
   *
   * @return
   * @author JohnDeng
   * @dateTime 2019年5月15日下午4:07:46
   */
  private static RequestConfig getRequestConfig() {

    return RequestConfig.custom().setConnectTimeout(60000).setConnectionRequestTimeout(60000)
        .setSocketTimeout(60000).build();
  }

  /**
   * 关闭流
   *
   * @author JohnDeng
   * @dateTime 2019年5月15日下午4:07:56
   */
  private void close() {
    try {
      httpClick.close();
    } catch (IOException e) {
      e.printStackTrace();
    }
  }

  /**
   * POST
   */
  public static HttpClickResponse doHttpPost(HttpClickRequest request) {
    HttpClickUtils httpClickUtils = new HttpClickUtils();
    httpClickUtils.initHttpClick();
    HttpRequestBase httpRequestBase = new HttpPost(request.getUrl());
    httpRequestBase.setConfig(getRequestConfig());
    return httpClickUtils.sendRequest(request, httpRequestBase);
  }

  /**
   * https:POST 发送https请求
   */
  public static HttpClickResponse doHttpsPost(HttpClickRequest request) {
    HttpClickUtils httpClickUtils = new HttpClickUtils();
    httpClickUtils.createSslClientDefault();
    HttpRequestBase httpRequestBase = new HttpPost(request.getUrl());
    httpRequestBase.setConfig(getRequestConfig());
    return httpClickUtils.sendRequest(request, httpRequestBase);
  }

  /**
   * GET
   */
  public static HttpClickResponse doHttpGet(HttpClickRequest request) {
    HttpClickUtils httpClickUtils = new HttpClickUtils();
    httpClickUtils.initHttpClick();
    HttpRequestBase httpRequestBase = new HttpGet(request.getUrl());
    httpRequestBase.setConfig(getRequestConfig());
    return httpClickUtils.sendRequest(request, httpRequestBase);
  }


  /**
   * 调用综合服务平台POST请求
   */
  public static HttpClickResponse doPost(HttpClickRequest request) {
    HttpClickResponse httpClickResponse = new HttpClickResponse();
    HttpResponse response = null;
    HttpClient httpclient = HttpClientBuilder.create().build();
    HttpPost httppost = new HttpPost(request.getUrl());
    httppost.addHeader("Content-type", "application/x-www-form-urlencoded");
    httppost.addHeader("Connection", "keep-alive");
    httppost.addHeader("Cache-Control", "max-age=0");
    httppost.addHeader("User-Agent", "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.0) ");
    httppost.addHeader("Accept", "application/json, text/html,text/javascript, */*");
    try {
      httppost.setEntity(new UrlEncodedFormEntity(mapToNameValuePairList(request.getParams()), "UTF-8"));
      httppost.setConfig(getRequestConfig());
      response = httpclient.execute(httppost);
      if (response.getStatusLine().getStatusCode() == OK_VALUE) {
        String result = EntityUtils.toString(response.getEntity(), "UTF-8");
        httpClickResponse = new HttpClickResponse();
        httpClickResponse.setStatusCode(response.getStatusLine().getStatusCode());
        httpClickResponse.setBodyParams(result);
      }
    } catch (UnsupportedEncodingException e) {
      e.printStackTrace();
    } catch (ClientProtocolException e) {
      e.printStackTrace();
    } catch (IOException e) {
      e.printStackTrace();
    }
    return httpClickResponse;
  }

}
